package com;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NeedleBoxAllocator {

    // 版本号
    public static final String VERSION = "V1.00";

    public static void main(String[] args) {
        // 输出版本号
        System.out.println("针盒分配程序 " + VERSION);
        System.out.println();

        // JSON 数据
        String json = "{\n" +
                "  \"macCode\": \"E001\",\n" +
                "  \"transCode\": \"dgas-ihewotru8r-t7345rw\",\n" +
                "  \"axles\": 10,\n" +
                "  \"drillArray\": [\n" +
                "    {\n" +
                "      \"tools\": \"T01\",\n" +
                "      \"drillSize\": \"3175\",\n" +
                "      \"drillCount\": 3,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T02\",\n" +
                "      \"drillSize\": \"0200\",\n" +
                "      \"drillCount\": 118,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 1\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T03\",\n" +
                "      \"drillSize\": \"0225\",\n" +
                "      \"drillCount\": 80,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 0\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T04\",\n" +
                "      \"drillSize\": \"0250\",\n" +
                "      \"drillCount\": 60,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T05\",\n" +
                "      \"drillSize\": \"0275\",\n" +
                "      \"drillCount\": 28,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T06\",\n" +
                "      \"drillSize\": \"0300\",\n" +
                "      \"drillCount\": 22,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 4\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T07\",\n" +
                "      \"drillSize\": \"0350\",\n" +
                "      \"drillCount\": 16,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T08\",\n" +
                "      \"drillSize\": \"0400\",\n" +
                "      \"drillCount\": 8,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 3\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T09\",\n" +
                "      \"drillSize\": \"0450\",\n" +
                "      \"drillCount\": 6,\n" +
                "      \"holeType\": \"2\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T10\",\n" +
                "      \"drillSize\": \"0450\",\n" +
                "      \"drillCount\": 4,\n" +
                "      \"holeType\": \"2\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T11\",\n" +
                "      \"drillSize\": \"0500\",\n" +
                "      \"drillCount\": 3,\n" +
                "      \"holeType\": \"2\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T12\",\n" +
                "      \"drillSize\": \"0650\",\n" +
                "      \"drillCount\": 4,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 1\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T13\",\n" +
                "      \"drillSize\": \"5000\",\n" +
                "      \"drillCount\": 1,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 2\n" +
                "    },\n" +
                "    {\n" +
                "      \"tools\": \"T14\",\n" +
                "      \"drillSize\": \"6000\",\n" +
                "      \"drillCount\": 2,\n" +
                "      \"holeType\": \"1\",\n" +
                "      \"drillGrindCount\": 1\n" +
                "    }\n" +
                "  ],\n" +
                "  \"Timestamp\": \"2024-12-10 22:31:09\"\n" +
                "}";

        // 解析 JSON 数据
        JSONObject root = JSON.parseObject(json);
        JSONArray drillArray = root.getJSONArray("drillArray");

        // 配针任务处理
        List<NeedleBox> needleBoxes = allocateNeedleBoxes(drillArray);

        // 输出结果
        for (int i = 0; i < needleBoxes.size(); i++) {
            System.out.println("针盒 " + (i + 1) + ":");
            NeedleBox box = needleBoxes.get(i);
            for (int row = 0; row < box.getRows(); row++) {
                for (int col = 0; col < box.getCols(); col++) {
                    System.out.print(box.getToolAt(row, col) + "\t");
                }
                System.out.println();
            }
            System.out.println();
        }
    }

    // 配针任务分配逻辑
    public static List<NeedleBox> allocateNeedleBoxes(JSONArray drillArray) {
        List<NeedleBox> needleBoxes = new ArrayList<>();
        NeedleBox sampleBox = new NeedleBox(); // 样品盒
        needleBoxes.add(sampleBox);

        // 每个针盒有 50 个孔，按列从左到右排列
        int colsPerBox = 5; // 每个针盒有 5 列
        int rowsPerBox = 10; // 每列有 10 行

        // 遍历每种刀具，分配样刀到第一个针盒
        for (int i = 0; i < drillArray.size(); i++) {
            JSONObject drill = drillArray.getJSONObject(i);
            String tool = drill.getString("tools");
            int drillCount = drill.getIntValue("drillCount");

            // 样刀：每种刀具放一支到第一个针盒
            if (sampleBox.getCurrentToolCount() < colsPerBox * rowsPerBox) {
                sampleBox.addTool(tool);
            } else {
                // 如果第一个针盒已满，创建新的样品盒
                NeedleBox newSampleBox = new NeedleBox();
                needleBoxes.add(newSampleBox);
                newSampleBox.addTool(tool);
                sampleBox = newSampleBox;
            }

            // 备用刀具：drillCount - 1
            int backupCount = drillCount - 1;
            if (backupCount > 0) {
                // 分配备用刀具到备用针盒
                allocateBackupTools(needleBoxes, tool, backupCount, colsPerBox, rowsPerBox);
            }
        }

        return needleBoxes;
    }

    // 备用刀具分配逻辑
    public static void allocateBackupTools(List<NeedleBox> needleBoxes, String tool, int backupCount, int colsPerBox, int rowsPerBox) {
        int toolsPerColumn = rowsPerBox; // 每列 10 个孔

        // 当前备用针盒索引（从样品盒之后开始）
        int backupBoxIndex = 1;
        while (backupBoxIndex < needleBoxes.size() && needleBoxes.get(backupBoxIndex).isSampleBox()) {
            backupBoxIndex++;
        }

        // 如果没有备用针盒，创建一个
        if (backupBoxIndex >= needleBoxes.size()) {
            NeedleBox backupBox = new NeedleBox(false); // 标记为备用针盒
            needleBoxes.add(backupBox);
        }

        NeedleBox currentBox = needleBoxes.get(backupBoxIndex);
        int remainingTools = backupCount;

        while (remainingTools > 0) {
            // 检查当前列是否已满或是否需要切换列
            if (currentBox.getCurrentColumnTools().size() >= toolsPerColumn) {
                currentBox.nextColumn();
            }

            // 如果当前列为空，初始化
            if (!currentBox.getCurrentColumnTools().containsKey(tool)) {
                currentBox.getCurrentColumnTools().put(tool, 0);
            }

            // 计算当前列中可以放置的数量
            int availableInColumn = toolsPerColumn - currentBox.getCurrentColumnTools().values().stream().mapToInt(Integer::intValue).sum();
            int toolsToPlace = Math.min(remainingTools, availableInColumn);

            // 如果当前列已经有其他刀具，只能放置到当前列剩余的位置
            if (!currentBox.getCurrentColumnTools().isEmpty() && currentBox.getCurrentColumnTools().size() > 1) {
                toolsToPlace = 0; // 如果当前列有多种刀具，不再放置新的
            }

            if (toolsToPlace == 0) {
                // 切换到下一列
                currentBox.nextColumn();
                currentBox.getCurrentColumnTools().clear(); // 清空当前列的刀具记录
                toolsToPlace = Math.min(remainingTools, toolsPerColumn);
            }

            // 放置刀具
            for (int i = 0; i < toolsToPlace; i++) {
                if (currentBox.getCurrentToolCount() >= colsPerBox * rowsPerBox) {
                    // 如果当前针盒已满，创建新的备用针盒
                    NeedleBox newBackupBox = new NeedleBox(false);
                    needleBoxes.add(newBackupBox);
                    currentBox = newBackupBox;
                    backupBoxIndex = needleBoxes.size() - 1;
                    currentBox.nextColumn(); // 确保新针盒从第一列开始
                    currentBox.getCurrentColumnTools().clear(); // 清空当前列的刀具记录
                }
                currentBox.addTool(tool);
                // 检查 tool 是否存在
                if (currentBox.getCurrentColumnTools().containsKey(tool)) {
                    currentBox.getCurrentColumnTools().put(tool, currentBox.getCurrentColumnTools().get(tool) + 1);
                } else {
                    currentBox.getCurrentColumnTools().put(tool, 1);
                }
            }

            remainingTools -= toolsToPlace;
        }
    }
}

// 针盒类
class NeedleBox {
    private List<List<String>> grid; // 针盒的网格
    private int rows; // 行数
    private int cols; // 列数
    private int currentRow; // 当前行
    private int currentCol; // 当前列
    private int toolCount; // 当前工具数量
    private boolean isSampleBox; // 是否是样品盒
    private Map<String, Integer> currentColumnTools; // 当前列中的刀具及其数量

    public NeedleBox() {
        this(true); // 默认是样品盒
    }

    public NeedleBox(boolean isSampleBox) {
        this.rows = 10; // 每列 10 行
        this.cols = 5; // 每个针盒 5 列
        this.grid = new ArrayList<>();
        for (int i = 0; i < rows; i++) {
            List<String> row = new ArrayList<>();
            for (int j = 0; j < cols; j++) {
                row.add(""); // 初始化为空
            }
            grid.add(row);
        }
        this.currentRow = 0;
        this.currentCol = 0;
        this.toolCount = 0;
        this.isSampleBox = isSampleBox;
        this.currentColumnTools = new HashMap<>(); // 初始化 currentColumnTools
    }

    // 添加工具到针盒
    public void addTool(String tool) {
        grid.get(currentRow).set(currentCol, tool);
        toolCount++;

        // 更新当前行列
        currentRow++;
        if (currentRow >= rows) {
            currentRow = 0;
            currentCol++;
        }
    }

    // 获取工具在指定位置
    public String getToolAt(int row, int col) {
        if (row < 0 || row >= rows || col < 0 || col >= cols) {
            throw new IndexOutOfBoundsException("超出针盒范围");
        }
        return grid.get(row).get(col);
    }

    // 获取行数
    public int getRows() {
        return rows;
    }

    // 获取列数
    public int getCols() {
        return cols;
    }

    // 获取当前工具数量
    public int getCurrentToolCount() {
        return toolCount;
    }

    // 获取当前列
    public int getCurrentColumn() {
        return currentCol;
    }

    // 获取当前行
    public int getCurrentRow() {
        return currentRow;
    }

    // 是否是样品盒
    public boolean isSampleBox() {
        return isSampleBox;
    }

    // 切换到下一列
    public void nextColumn() {
        currentCol++;
        if (currentCol >= cols) {
            currentCol = 0;
        }
        currentRow = 0;
        currentColumnTools.clear();
    }

    // 获取当前列中的刀具及其数量
    public Map<String, Integer> getCurrentColumnTools() {
        return currentColumnTools;
    }
}
